﻿using CommonEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace CommonDevelop
{
    /// <summary>
    /// 页面业务使用
    /// </summary>
    public sealed class PageUtility
    {
        /// <summary>
        /// 加密表单转换成键值对
        /// </summary>
        public static Dictionary<string, string> GetDic(string Encode)
        {
            if (string.IsNullOrEmpty(Encode))
                return new Dictionary<string, string>();

            string result = CommonOP.Decode64Url(Encode);
            return GetDicByQueryString(result);
        }

        public static Dictionary<string, string> GetDicByQueryString(string queryString)
        {
            if (string.IsNullOrEmpty(queryString))
                return new Dictionary<string, string>();

            return parseRequestParam(queryString);
        }
        
        public static T EffectiveMap<T>(Dictionary<string, string> data) where T : class, new()
        {
            if (data.IsNullOrEmpty())
                return default(T);

            Dictionary<string, Tuple<Type, bool>> dic = ToDic<T>();
            Dictionary<string, object> dicEn = new Dictionary<string, object>();
            foreach (var item in dic)
            {
                if (item.Value == null)
                    continue;

                Tuple<Type, bool> pt = item.Value;
                #region--In dicEn--

                foreach (var D in data)
                {
                    if (D.Key == item.Key)
                    {
                        if (pt.Item1 == typeof(DateTime))
                        {
                            DateTime date = DateTime.Now;
                            if (DateTime.TryParse(D.Value, out date))
                                dicEn.Add(item.Key, date);
                            else if (pt.Item2)
                                dicEn.Add(item.Key, null);
                            else
                                dicEn.Add(item.Key, date);
                        }
                        else if (pt.Item1 == typeof(Guid))
                        {
                            Guid G = Guid.Empty;
                            if (Guid.TryParse(D.Value, out G))
                                dicEn.Add(item.Key, G);
                            else if (pt.Item2)
                                dicEn.Add(item.Key, null);
                            else
                                dicEn.Add(item.Key, G);
                        }
                        else if (pt.Item1 == typeof(int))
                        {
                            int G = 0;
                            if (int.TryParse(D.Value, out G))
                                dicEn.Add(item.Key, G);
                            else if (pt.Item2)
                                dicEn.Add(item.Key, null);
                            else
                                dicEn.Add(item.Key, G);
                        }
                        else if (pt.Item1 == typeof(long))
                        {
                            long G = 0;
                            if (long.TryParse(D.Value, out G))
                                dicEn.Add(item.Key, G);
                            else if (pt.Item2)
                                dicEn.Add(item.Key, null);
                            else
                                dicEn.Add(item.Key, G);
                        }
                        else if (pt.Item1 == typeof(decimal))
                        {
                            decimal G = 0;
                            if (decimal.TryParse(D.Value, out G))
                                dicEn.Add(item.Key, G);
                            else if (pt.Item2)
                                dicEn.Add(item.Key, null);
                            else
                                dicEn.Add(item.Key, G);
                        }
                        else if (pt.Item1 == typeof(double))
                        {
                            double G = 0;
                            if (double.TryParse(D.Value, out G))
                                dicEn.Add(item.Key, G);
                            else if (pt.Item2)
                                dicEn.Add(item.Key, null);
                            else
                                dicEn.Add(item.Key, G);
                        }
                        else if (pt.Item1 == typeof(bool))
                        {
                            bool G = false;
                            if (bool.TryParse(D.Value, out G))
                                dicEn.Add(item.Key, G);
                            else if ("on".Equals(D.Value))
                                dicEn.Add(item.Key, true);
                            else if (pt.Item2)
                                dicEn.Add(item.Key, null);
                            else
                                dicEn.Add(item.Key, G);
                        }
                        else
                        {
                            dicEn.Add(item.Key, D.Value);
                        }
                        break;
                    }
                }

                #endregion
            }

            return DicToObject<T>(dicEn);
        }

        #region---内部操作---

        private static Dictionary<string, Tuple<Type, bool>> ToDic<T>() where T : class, new()
        {
            Dictionary<string, Tuple<Type, bool>> Dic = new Dictionary<string, Tuple<Type, bool>>();
            PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo prop in props)
            {
                Type pt = prop.PropertyType;
                bool IsCanNull = false;
                if (pt.IsGenericType && pt.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    pt = pt.GetGenericArguments()[0];
                    IsCanNull = true;
                }
                Dic.Add(prop.Name, new Tuple<Type, bool>(pt, IsCanNull));
            }
            return Dic;
        }
        private static T DicToObject<T>(Dictionary<string, object> dic) where T : new()
        {
            T Em = new T();
            Type t = typeof(T);

            try
            {
                foreach (var d in dic)
                {
                    var value = d.Value;
                    t.GetProperty(d.Key).SetValue(Em, value);
                }
            }
            catch
            {
                throw;
            }
            return Em;
        }
        private static Dictionary<string, string> parseRequestParam(string url)
        {
            Dictionary<string, string> map = new Dictionary<string, string>();
            string parsedStr = url;
            if (parsedStr.Contains("&"))
            {
                string[] multiParamObj = parsedStr.Split('&');
                foreach (var obj in multiParamObj)
                {
                    parseBasicParam(map, obj);
                }
                return map;
            }
            parseBasicParam(map, parsedStr);
            return map;
        }
        private static void parseBasicParam(Dictionary<string, string> map, string str)
        {
            string[] paramObj = str.Split('=');
            if (paramObj.Length < 2)
            {
                return;
            }
            map.Add(paramObj[0], paramObj[1]);
        }

        #endregion

        public static T FormMap<T>(string Encode) where T : class, new()
        {
            try
            {
                Dictionary<string, string> dic = GetDic(Encode);
                if (!dic.Any())
                    return default(T);

                return EffectiveMap<T>(dic);
            }
            catch
            {
                return default(T);
            }
        }

        public static T FormJson<T>(string Encode) where T : class, new()
        {
            if (Encode.IsEmpty())
                return default(T);

            try
            {
                string result = CommonOP.Decode64Url(Encode);
                return JsonHelper.DeserializeObject<T>(result);
            }
            catch
            {
                return default(T);
            }
        }
    }
}
